---
title: Editable
description: Using the editable machine in your project.
package: "@zag-js/editable"
---

Editable is an input field used for editing a single line of text. It renders as
static text and transforms into a text input field when then edit interaction is
triggered (click, focus, or double-click).

<Resources pkg="@zag-js/editable" />

<Showcase id="Editable" />

**Features**

- Use custom controls for the editable
- Pressing `Enter` commits the input value
- Pressing `Esc` reverts the value
- Activate edit mode by double-clicking or focusing on the preview text
- Auto-resize input to fit content

## Installation

To use the editable machine in your project, run the following command in your
command line:

<CodeSnippet id="editable/installation.mdx" />

## Anatomy

To set up the editable correctly, you'll need to understand its anatomy and how
we name its parts.

> Each part includes a `data-part` attribute to help identify them in the DOM.

<Anatomy id="editable" />

## Usage

First, import the editable package into your project

```jsx
import * as editable from "@zag-js/editable"
```

The editable package exports two key functions:

- `machine` — The state machine logic for the editable widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> You'll need to provide a unique `id` to the `useMachine` hook. This is used to
> ensure that every part has a unique identifier.

Next, import the required hooks and functions for your framework and use the
editable machine in your project 🔥

<CodeSnippet id="editable/usage.mdx" />

### Setting the initial value

To set the initial value of the editable, pass the `defaultValue` property to
the machine's context.

```jsx {2}
const service = useMachine(editable.machine, {
  defaultValue: "Hello World",
})
```

### Listening for value changes

The editable machine supports two ways of listening for value changes:

- `onValueChange`: called when value changes.
- `onValueCommit`: called when the value is committed.

```jsx {2-4}
const service = useMachine(editable.machine, {
  onValueChange(details) {
    console.log("Value changed", details.value)
  },
  onValueCommit(details) {
    console.log("Value submitted", details.value)
  },
})
```

### Using custom controls

In some cases, you might need to use custom controls to toggle the edit and read
mode. We use the render prop pattern to provide access to the internal state of
the component.

<CodeSnippet id="editable/custom-controls.mdx" />

### Auto-resizing

To auto-grow the editable as the content changes, pass the `autoResize: true`
property to the machine's context.

```jsx {2}
const service = useMachine(editable.machine, {
  autoResize: true,
})
```

When using autoresize, the input and preview elements should not have any
styles. Use `all: unset` if needed and pass any styles to the "area" element
since its shared by the input and preview elements.

### Setting a maxWidth

It is a common pattern to set a maximum of the editable as it auto-grows. To
achieve this, set the `maxWidth` property of the machine's context to the
desired value.

```jsx {2-3}
const service = useMachine(editable.machine, {
  autoResize: true,
  maxWidth: "320px",
})
```

When the editable reaches the specified max-width, it'll clip the preview text
with an ellipsis.

### Editing with double click

The editable supports two modes of activating the "edit" state:

- when the preview part is focused (with pointer or keyboard).
- when the preview part is double-clicked.

To change the mode to "double-click", set the `activationMode: 'dblclick'`
property in the machine's context.

```jsx {2}
const service = useMachine(editable.machine, {
  activationMode: "dblclick",
})
```

### Usage with Textarea

The editable machine supports using a `textarea` instead of an `input` field.
When a textarea is used, the editable will commit the value on `Cmd + Enter` or
`Ctrl + Enter`.

> Use the `api.inputProps` to spread the input props to the textarea element.
> You might need to cast the input props to the correct type.

```tsx {2}
<textarea {...(api.inputProps as HTMLTextareaProps<HTMLTextareaElement>)} />
```

## Styling guide

Earlier, we mentioned that each editable part has a `data-part` attribute added
to them to select and style them in the DOM.

### Focused state

When the editable is in the focused mode, we set a `data-focus` attribute on the
"area" part.

```css
[data-part="area"][data-focus] {
  /* CSS for the editable's focus state */
}
```

### Empty state

When the editable's value is empty, we set a `data-empty` attribute on the
"area" part.

```css
[data-part="area"][data-empty] {
  /* CSS for the editable's focus state */
}
```

### Disabled state

When the editable is disabled, we set a `data-disabled` attribute on the "area"
part.

```css
[data-part="area"][data-disabled] {
  /* CSS for the editable's focus state */
}
```

## Methods and Properties

### Machine Context

The editable machine exposes the following context properties:

<ContextTable name="editable" />

### Machine API

The editable `api` exposes the following methods:

<ApiTable name="editable" />

### Data Attributes

<DataAttrTable name="editable" />

## Accessibility

### Keyboard Interactions

<KeyboardTable name="editable" />
